package org.deep;

public class ByteUtil {
    public static void putShort(boolean lowFirst, byte[] b, int index, short value) {
        if (lowFirst) {
            b[index] = (byte) (value);
            b[index + 1] = (byte) (value >> 8);
        } else {
            b[index] = (byte) (value >> 8);
            b[index + 1] = (byte) (value);
        }
    }

    public static short getShort(boolean lowFirst, byte[] b, int index) {
        if (lowFirst) {
            return (short) (((b[index + 1] << 8) | b[index] & 0xff));
        } else {
            return (short) (((b[index] << 8) | b[index + 1] & 0xff));
        }
    }

    public static void putInt(boolean lowFirst, byte[] bb, int x, int index) {
        if (lowFirst) {
            bb[index] = (byte) (x);
            bb[index + 1] = (byte) (x >> 8);
            bb[index + 2] = (byte) (x >> 16);
            bb[index + 3] = (byte) (x >> 24);
        } else {
            bb[index] = (byte) (x >> 24);
            bb[index + 1] = (byte) (x >> 16);
            bb[index + 2] = (byte) (x >> 8);
            bb[index + 3] = (byte) (x);
        }
    }

    public static int getInt(boolean lowFirst, byte[] bb, int index) {
        if (lowFirst) {
            return (((bb[index + 3] & 0xff) << 24)
                    | ((bb[index + 2] & 0xff) << 16)
                    | ((bb[index + 1] & 0xff) << 8)
                    | ((bb[index] & 0xff)));
        } else {
            return (((bb[index + 3] & 0xff))
                    | ((bb[index + 2] & 0xff) << 8)
                    | ((bb[index + 1] & 0xff) << 16)
                    | ((bb[index] & 0xff) << 24));
        }

    }

    public static void putLong(boolean lowFirst, byte[] bb, long x, int index) {
        if (lowFirst) {
            bb[index + 7] = (byte) (x >> 56);
            bb[index + 6] = (byte) (x >> 48);
            bb[index + 5] = (byte) (x >> 40);
            bb[index + 4] = (byte) (x >> 32);
            bb[index + 3] = (byte) (x >> 24);
            bb[index + 2] = (byte) (x >> 16);
            bb[index + 1] = (byte) (x >> 8);
            bb[index] = (byte) (x);
        } else {
            bb[index + 7] = (byte) (x);
            bb[index + 6] = (byte) (x >> 8);
            bb[index + 5] = (byte) (x >> 16);
            bb[index + 4] = (byte) (x >> 24);
            bb[index + 3] = (byte) (x >> 32);
            bb[index + 2] = (byte) (x >> 40);
            bb[index + 1] = (byte) (x >> 48);
            bb[index] = (byte) (x >> 56);
        }
    }

    public static long getLong(boolean lowFirst, byte[] bb, int index) {
        if (lowFirst) {
            return ((((long) bb[index + 7] & 0xff) << 56)
                    | (((long) bb[index + 6] & 0xff) << 48)
                    | (((long) bb[index + 5] & 0xff) << 40)
                    | (((long) bb[index + 4] & 0xff) << 32)
                    | (((long) bb[index + 3] & 0xff) << 24)
                    | (((long) bb[index + 2] & 0xff) << 16)
                    | (((long) bb[index + 1] & 0xff) << 8)
                    | (((long) bb[index] & 0xff)));
        } else {
            return ((((long) bb[index + 7] & 0xff))
                    | (((long) bb[index + 6] & 0xff) << 8)
                    | (((long) bb[index + 5] & 0xff) << 16)
                    | (((long) bb[index + 4] & 0xff) << 24)
                    | (((long) bb[index + 3] & 0xff) << 32)
                    | (((long) bb[index + 2] & 0xff) << 40)
                    | (((long) bb[index + 1] & 0xff) << 48)
                    | (((long) bb[index] & 0xff) << 56));
        }
    }

    public static void putFloat(boolean lowFirst, byte[] bb, float x, int index) {
        int l = Float.floatToIntBits(x);
        for (int i = 0; i < 4; i++) {
            bb[lowFirst ? index + i : index + 3 - i] = new Integer(l).byteValue();
            l = l >> 8;
        }
    }

    public static float getFloat(boolean lowFirst, byte[] b, int index) {
        int l;
        if (lowFirst) {
            l = b[index];
            l &= 0xff;
            l |= ((long) b[index + 1] << 8);
            l &= 0xffff;
            l |= ((long) b[index + 2] << 16);
            l &= 0xffffff;
            l |= ((long) b[index + 3] << 24);
        } else {
            l = b[index + 3];
            l &= 0xff;
            l |= ((long) b[index + 2] << 8);
            l &= 0xffff;
            l |= ((long) b[index + 1] << 16);
            l &= 0xffffff;
            l |= ((long) b[index] << 24);
        }
        return Float.intBitsToFloat(l);
    }

    /**
     * byte[]格式化为16进制字符串
     *
     * @param buf              需要格式化数据
     * @param withIndex        是否显示下标
     * @param lineElementCount 每行显示多少个元素，超过即换行。默认为0时不换行
     * @return 格式化后的字符串
     */
    public static String conentToHexString(byte[] buf, boolean withIndex, int lineElementCount) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        sb.append(System.lineSeparator());
        for (int i = 0; i < buf.length; i++) {
            if (withIndex) {
                sb.append(String.format("{%d}", i));
            }
            sb.append(String.format("%02X", buf[i]));
            if (i < buf.length - 1) {
                sb.append(",");
            }
            if ((i + 1) % lineElementCount == 0) {
                sb.append(System.lineSeparator());
            }
        }
        sb.append(System.lineSeparator());
        sb.append("]");
        return sb.toString();
    }
}
